<template>
  <div class="t-table" :class="
    [ `t-table--${size}`, 
      `t-table--${theme}`,
      stripe ? 't-table--stripe':'',
      stripe ? `t-table--stripe--${theme}`:'',
      border ? 't-table--border':'',
      border ? `t-table--border--${theme}`:'',]">
    <slot></slot>
    <div class="headWrapperClass" ref="headWrapper">
      <t-table-head ref="head" :store="store"></t-table-head>
    </div>
    <div :class="bodyWrapperClass" ref="bodyWrapper" @click="handleBodyWrapperClick">
      <t-table-body ref="body" :store="store"></t-table-body>
    </div>
    <div class="t-table__foot-wrapper" ref="footWrapper">
      <t-table-foot ref="foot" :store="store"></t-table-foot>
    </div>
  </div>
</template>

<script>
  import _ from 'lodash';
  import PerfectScrollbar from 'perfect-scrollbar';
  import TableStore from '@/components/table/table-store';
  import TTableHead from '@/components/table/table-head';
  import TTableBody from '@/components/table/table-body';
  import TTableFoot from '@/components/table/table-foot';
  import mousewheel from '@/components/utils/mousewheel';
  
  export default {
    name: 'TTable',
    components: {
      TTableHead,
      TTableBody,
      TTableFoot,
    },
    data() {
      const store = new TableStore(this);
      return {
        store,
        dp: null,
      };
    },
    props: {
      width: [String, Number],
      height: [String, Number],
      theme: {
        default: 'extra-light-black',
        validator: (str) => {
          if (str === 'blue' || str === 'extra-light-black') {
            return true;
          }
          return false;
        },
      },
      border: Boolean,
      stripe: Boolean,
      size: {
        default: 'normal',
        validator: (str) => {
          if (str === 'mini' || str === 'normal' || str === 'large' || str === 'small') {
            return true;
          }
          return false;
        },
      },
      items: {
        type: Array,
        required: true,
        default: () => {
          return [];
        },
      },
      sortable: Boolean,
      sort: {
        validator: (obj) => {
          if (obj && typeof obj === 'object') {
            if (obj.prop && typeof obj.prop === 'string') {
              if (obj.order && typeof obj.order === 'string' && (obj.order === 'ascending' || obj.order === 'descending')) {
                if (obj.method && typeof obj.method === 'function') {
                  return true;
                }
              }
            }
          }
          return false;
        },
        default: () => {
          return {
            prop: 'id',
            order: 'ascending',
            method: (a, b) => {
              return a.id > b.id;
            },
          };
        },
      },
    },
    computed: {
      columns() {
        return this.store.state.columns;
      },
      elTable() {
        return this.$el;
      },
      elHead() {
        return this.$refs.head;
      },
      elHeadWrapper() {
        return this.$refs.headWrapper;
      },
      elBody() {
        return this.$refs.body;
      },
      elBodyWrapper() {
        return this.$refs.bodyWrapper;
      },
      elBodyWrapperEnableScrollY() {
        return this.elBody.offsetHeight > this.elBodyWrapper.offsetHeight;
      },
      elFoot() {
        return this.$refs.foot;
      },
      elFootWrapper() {
        return this.$refs.footWrapper;
      },
      headWrapperClass() {
        return `t-table--${this.size}__head-wrapper`;
      },
      bodyWrapperClass() {
        return `t-table--${this.size}__body-wrapper`;
      },
      currentItems() {
        return this.store.state.currentItems;
      },
      currentSortedItems() {
        return this.store.state.currentSortedItems;
      },
    },
    created() {
      this.$eventHub.$on('resize', () => {
        window.setTimeout(() => {
          if (!this.$el || !this.elHeadWrapper || !this.$refs.bodyWrapper) return;
          const tableHeight = parseInt(window.getComputedStyle(this.$el).height, 10);
          const headHeight = parseInt(window.getComputedStyle(this.elHeadWrapper).height, 10);
          const bodyHeight = tableHeight - headHeight;
          this.$refs.bodyWrapper.style.height = `${bodyHeight}px`;
          this.dp = new PerfectScrollbar(this.$refs.bodyWrapper, {
            wheelSpeed: 2,
            wheelPropagation: false,
          });
        }, 500);
      });
    },
    mounted() {
      this.bindEventHandler();
      this.$nextTick(() => {
        // set table height
        if (this.height) {
          this.setHeight(this.height);
        }
        // set table width
        if (this.width) {
          this.setWidth(this.width);
        }
        this.store.setSort(this.sort.prop, this.sort.order, this.sort.method);
        this.store.addAllItems(this.items);
        window.setTimeout(() => {
          if (!this.$el || !this.elHeadWrapper || !this.$refs.bodyWrapper) return;
          const tableHeight = parseInt(window.getComputedStyle(this.$el).height, 10);
          const headHeight = parseInt(window.getComputedStyle(this.elHeadWrapper).height, 10);
          const bodyHeight = tableHeight - headHeight;
          this.$refs.bodyWrapper.style.height = `${bodyHeight}px`;
          this.dp = new PerfectScrollbar(this.$refs.bodyWrapper, {
            wheelSpeed: 2,
            wheelPropagation: false,
          });
        }, 500);
      });
    },
    watch: {
      items(val) {
        this.store.clearItems();
        this.store.addAllItems(val);
      },
    },
    methods: {
      bindEventHandler() {
        const callback = _.throttle(this.scrollBodyWrapper, 150);
        mousewheel(this.elHeadWrapper, callback);
        mousewheel(this.elFootWrapper, callback);
      },
      // for table event
      handleBodyWrapperClick() {
        if (this.headWrapper) {
          this.headWrapper.scrollLeft = this.table.scrollLeft;
        }
        if (this.footWrapper) {
          this.footWrapper.scrollLeft = this.table.scrollLeft;
        }
      },
      // for table layout
      setWidth(val, prop = 'width') {
        this.elTable.style[prop] = `${val}rem`;
      },
      setHeight(val, prop = 'height') {
        this.elTable.style[prop] = `${val}rem`;
      },
      scrollBodyWrapper(event) {
        const {
          deltaX,
          deltaY,
        } = event;
        // for chrome
        if (Math.abs(deltaX) < Math.abs(deltaY)) return;
        // for w3c
        if (deltaX > 0) {
          this.bodyWrapper.scrollLeft += 10;
        } else if (deltaX < 0) {
          this.bodyWrapper.scrollLeft -= 10;
        }
      },
    },
  };

</script>